home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / prefix / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  32.2 KB  |  1,396 lines

  1. /***********************************************************************
  2.  *
  3.  * PROJECT:      PMake
  4.  * MODULE:      Prefix -- Utilities/Initialization
  5.  * FILE:      main.c
  6.  *
  7.  * AUTHOR:        Adam de Boor: Jul  4, 1989
  8.  *
  9.  * ROUTINES:
  10.  *    Name              Description
  11.  *    ----              -----------
  12.  *    main                Entry point
  13.  *    HandleToPrefix        Map a fhandle_t to a Prefix
  14.  *    NameToPrefix        Map an absolute name to a Prefix
  15.  *    Message                Write a message to the console
  16.  *    dprintf                Write debugging info to the console
  17.  *
  18.  * REVISION HISTORY:
  19.  *    Date      Name        Description
  20.  *    ----      ----        -----------
  21.  *    7/ 4/89      ardeb        Initial version
  22.  *
  23.  * DESCRIPTION:
  24.  *    Program to do stuff similar to Sprite's prefix table, thus
  25.  *    simplifying the task of administering a sizeable network of
  26.  *    workstations that require a consistent global filesystem for
  27.  *    PMake to operate correctly.
  28.  *
  29.  *     Copyright (c) Berkeley Softworks 1989
  30.  *     Copyright (c) Adam de Boor 1989
  31.  *
  32.  *     Permission to use, copy, modify, and distribute this
  33.  *     software and its documentation for any non-commercial purpose
  34.  *    and without fee is hereby granted, provided that the above copyright
  35.  *     notice appears in all copies.  Neither Berkeley Softworks nor
  36.  *     Adam de Boor makes any representations about the suitability of this
  37.  *     software for any purpose.  It is provided "as is" without
  38.  *     express or implied warranty.
  39.  *
  40.  ***********************************************************************/
  41. #ifndef lint
  42. static char *rcsid =
  43. "$Id: main.c,v 1.11 89/10/10 00:41:20 adam Exp $";
  44. #endif lint
  45.  
  46. #include    "prefix.h"
  47.  
  48. #include    <varargs.h>
  49. #include    <ctype.h>
  50. #include    <sys/signal.h>
  51.  
  52. #include    "rpc.h"
  53.  
  54. Lst            prefixes;           /* List of unmounted prefixes */
  55. Lst            freePrefixes;        /* List of freed Prefix records */
  56.  
  57. int            prefixSock;            /* Socket over which we talk to other
  58.                      * prefix daemons */
  59.  
  60. int        debug;                /* Non-zero if in debug mode */
  61. int            quiet;                /* Don't spew to the console */
  62.  
  63. struct sockaddr_in prefixMountAddr; /* Address of server for prefixes */
  64.  
  65. static FILE    *dbgStream;        /* Stream into which debugging output
  66.                      * should go */
  67.  
  68. /***********************************************************************
  69.  *                AllocPrefix
  70.  ***********************************************************************
  71.  * SYNOPSIS:        Allocate a new Prefix record
  72.  * CALLED BY:        EXTERNAL
  73.  * RETURN:        The Prefix * with only the generation field set.
  74.  * SIDE EFFECTS:    
  75.  *
  76.  * STRATEGY:
  77.  *
  78.  * REVISION HISTORY:
  79.  *    Name    Date        Description
  80.  *    ----    ----        -----------
  81.  *    ardeb    10/ 9/89    Initial Revision
  82.  *
  83.  ***********************************************************************/
  84. Prefix *
  85. AllocPrefix()
  86. {
  87.     Prefix  *pp;
  88.     
  89.     if (Lst_IsEmpty(freePrefixes)) {
  90.     pp = (Prefix *)malloc(sizeof(Prefix));
  91.     pp->generation = 0;
  92.     } else {
  93.     pp = (Prefix *)Lst_DeQueue(freePrefixes);
  94.     }
  95.  
  96.     return(pp);
  97. }
  98.  
  99. /***********************************************************************
  100.  *                FreePrefix
  101.  ***********************************************************************
  102.  * SYNOPSIS:        Free a prefix structure.
  103.  * CALLED BY:        EXTERNAL
  104.  * RETURN:        Nothing
  105.  * SIDE EFFECTS:    None
  106.  *
  107.  * STRATEGY:
  108.  *    Place the prefix on the freePrefixes list after upping its
  109.  *    generation number. The prefix is removed from the prefixes list
  110.  *    as well, but no other fields are altered.
  111.  *
  112.  * REVISION HISTORY:
  113.  *    Name    Date        Description
  114.  *    ----    ----        -----------
  115.  *    ardeb    10/ 9/89    Initial Revision
  116.  *
  117.  ***********************************************************************/
  118. void
  119. FreePrefix(pp)
  120.     Prefix      *pp;
  121. {
  122.     LstNode     ln;
  123.  
  124.     ln = Lst_Member(prefixes, (ClientData)pp);
  125.     if (ln != NILLNODE) {
  126.     Lst_Remove(prefixes, ln);
  127.     }
  128.  
  129.     pp->generation += 1;
  130.     (void)Lst_AtEnd(freePrefixes, (ClientData)pp);
  131. }
  132.  
  133.  
  134.  
  135. /***********************************************************************
  136.  *                HandleToPrefix
  137.  ***********************************************************************
  138.  * SYNOPSIS:        Convert an NFS handle to a Prefix *
  139.  * CALLED BY:        EXTERNAL
  140.  * RETURN:        The Prefix * for the FS.
  141.  * SIDE EFFECTS:    None
  142.  *
  143.  * STRATEGY:
  144.  *
  145.  * REVISION HISTORY:
  146.  *    Name    Date        Description
  147.  *    ----    ----        -----------
  148.  *    ardeb    7/ 4/89        Initial Revision
  149.  *
  150.  ***********************************************************************/
  151. Prefix *
  152. HandleToPrefix(handle)
  153.     fhandle_t    *handle;        /* Handle to be converted. Should contain
  154.                  * the ascii representation of the Prefix
  155.                  * structure's address, if it's valid */
  156. {
  157.     PrefixHandle    *php = (PrefixHandle *)handle;
  158.  
  159.     if ((php->type != PH_REGULAR) ||
  160.     (php->rd.generation != php->rd.pp->generation) ||
  161.     (Lst_Member(prefixes, (ClientData)php->rd.pp) == NILLNODE))
  162.     {
  163.     return(PREFIX_STALE);
  164.     } else {
  165.     return(php->rd.pp);
  166.     }
  167. }
  168.  
  169.  
  170. /***********************************************************************
  171.  *                PrefixToHandle
  172.  ***********************************************************************
  173.  * SYNOPSIS:        Create an NFS handle to return for a prefix.
  174.  * CALLED BY:        EXTERNAL
  175.  * RETURN:        Nothing
  176.  * SIDE EFFECTS:    The handle is filled in.
  177.  *
  178.  * STRATEGY:
  179.  *
  180.  * REVISION HISTORY:
  181.  *    Name    Date        Description
  182.  *    ----    ----        -----------
  183.  *    ardeb    10/ 9/89    Initial Revision
  184.  *
  185.  ***********************************************************************/
  186. void
  187. PrefixToHandle(pp, handle)
  188.     Prefix      *pp;
  189.     fhandle_t    *handle;
  190. {
  191.     PrefixHandle    *php;
  192.  
  193.     php = (PrefixHandle *)handle;
  194.     
  195.     /*
  196.      * Make sure unused bytes are zero.
  197.      */
  198.     bzero(handle, sizeof(*handle));
  199.  
  200.     /*
  201.      * Store the handle and the generation number
  202.      */
  203.     php->rd.type = PH_REGULAR;
  204.     php->rd.generation = pp->generation;
  205.     php->rd.pp = pp;
  206. }
  207.  
  208.  
  209. /***********************************************************************
  210.  *                NameToPrefix
  211.  ***********************************************************************
  212.  * SYNOPSIS:        Given an absolute name, return the Prefix for it
  213.  * CALLED BY:        various and sundry
  214.  * RETURN:        The Prefix * or NULL
  215.  * SIDE EFFECTS:    None
  216.  *
  217.  * STRATEGY:
  218.  *
  219.  * REVISION HISTORY:
  220.  *    Name    Date        Description
  221.  *    ----    ----        -----------
  222.  *    ardeb    7/ 8/89        Initial Revision
  223.  *
  224.  ***********************************************************************/
  225. Prefix    *
  226. NameToPrefix(path)
  227.     char        *path;
  228. {
  229.     LstNode     ln;
  230.     Prefix      *pp;
  231.  
  232.     for (ln = Lst_First(prefixes); ln != NILLNODE; ln = Lst_Succ(ln)) {
  233.     pp = (Prefix *)Lst_Datum(ln);
  234.  
  235.     if (strcmp(pp->path, path) == 0) {
  236.         return(pp);
  237.     }
  238.     }
  239.     
  240.     return((Prefix *)NULL);
  241. }
  242.     
  243.  
  244. /***********************************************************************
  245.  *                Message
  246.  ***********************************************************************
  247.  * SYNOPSIS:        Print a message on the console
  248.  * CALLED BY:        Things Of Import
  249.  * RETURN:        Nothing
  250.  * SIDE EFFECTS:    None
  251.  *
  252.  * STRATEGY:
  253.  *
  254.  * REVISION HISTORY:
  255.  *    Name    Date        Description
  256.  *    ----    ----        -----------
  257.  *    ardeb    7/ 7/89        Initial Revision
  258.  *
  259.  ***********************************************************************/
  260. void
  261. Message(fmt, va_alist)
  262.     char        *fmt;        /* Format string for message */
  263.     va_dcl                  /* Other args... */
  264. {
  265.     va_list     args;
  266.  
  267.     /*
  268.      * Start examining the args.
  269.      */
  270.     va_start(args);
  271.  
  272.     /*
  273.      * Label the message
  274.      */
  275.     fprintf(stderr, "prefix: ");
  276.  
  277.     /*
  278.      * Use vfprintf to print the message if it's around (better than _doprnt
  279.      * since it handles some of the newer architectures...)
  280.      * If vfprintf isn't around, we'll have to settle for _doprnt.
  281.      */
  282.     vfprintf(stderr, fmt, args);
  283.  
  284.     /*
  285.      * Terminate the message with a newline and make sure the stream is
  286.      * flushed.
  287.      */
  288.     putc('\n', stderr);
  289.     fflush(stderr);
  290.  
  291.     /*
  292.      * Finish processing the args
  293.      */
  294.     va_end(args);
  295.  
  296.     /*
  297.      * Route output to debug log too, if not the console
  298.      */
  299.     if (debug && dbgStream != stderr) {
  300.     va_start(args);
  301.     fprintf(dbgStream, "prefix: ");
  302.     vfprintf(dbgStream, fmt, args);
  303.     putc('\n', dbgStream);
  304.     fflush(dbgStream);
  305.     va_end(args);
  306.     }
  307.  
  308. }
  309.  
  310.  
  311. /***********************************************************************
  312.  *                dprintf
  313.  ***********************************************************************
  314.  * SYNOPSIS:        Print if debugging enabled
  315.  * CALLED BY:        Lots Of Unimportant Things
  316.  * RETURN:        Nothing
  317.  * SIDE EFFECTS:    No
  318.  *
  319.  * STRATEGY:
  320.  *
  321.  * REVISION HISTORY:
  322.  *    Name    Date        Description
  323.  *    ----    ----        -----------
  324.  *    ardeb    7/ 7/89        Initial Revision
  325.  *
  326.  ***********************************************************************/
  327. void
  328. dprintf(fmt, va_alist)
  329.     char        *fmt;
  330.     va_dcl
  331. {
  332.     va_list     args;
  333.  
  334.     /*
  335.      * Start examining the args.
  336.      */
  337.     va_start(args);
  338.  
  339.     if (debug) {
  340.     vfprintf(dbgStream, fmt, args);
  341.     fflush(dbgStream);
  342.     }
  343.  
  344.     /*
  345.      * Finish with the arguments
  346.      */
  347.     va_end(args);
  348. }
  349.  
  350. #ifdef MEM_TRACE
  351.  
  352. /***********************************************************************
  353.  *                MessageFlush
  354.  ***********************************************************************
  355.  * SYNOPSIS:        Function required by tracing malloc to spew a string
  356.  *                to stderr.
  357.  * CALLED BY:        error in malloc.c
  358.  * RETURN:        Nothing
  359.  * SIDE EFFECTS:    The string is written to stream 2
  360.  *
  361.  * STRATEGY:
  362.  *
  363.  * REVISION HISTORY:
  364.  *    Name    Date        Description
  365.  *    ----    ----        -----------
  366.  *    ardeb    7/ 6/89        Initial Revision
  367.  *
  368.  ***********************************************************************/
  369. void
  370. MessageFlush(str)
  371.     char        *str;
  372. {
  373.     write(2, str, strlen(str));
  374. }
  375.  
  376.  
  377. /***********************************************************************
  378.  *                DumpMemStats
  379.  ***********************************************************************
  380.  * SYNOPSIS:        Dump the memory usage to /tmp/prefix.usage
  381.  * CALLED BY:        SIGHUP
  382.  * RETURN:        Nothing
  383.  * SIDE EFFECTS:
  384.  *
  385.  * STRATEGY:
  386.  *
  387.  * REVISION HISTORY:
  388.  *    Name    Date        Description
  389.  *    ----    ----        -----------
  390.  *    ardeb    9/30/89        Initial Revision
  391.  *
  392.  ***********************************************************************/
  393. void
  394. DumpMemStats()
  395. {
  396.     FILE    *pu = fopen("/tmp/prefix.usage", "w");
  397.  
  398.     if (pu != NULL) {
  399.     extern int fprintf();
  400.  
  401.     MessageFlush("Dumping memory allocation statistics to /tmp/prefix.usage...");
  402.     malloc_printstats((void (*)())fprintf, (void *)pu);
  403.     fclose(pu);
  404.     MessageFlush("done\n");
  405.     }
  406. }
  407.  
  408. #endif /* MEM_TRACE */
  409.  
  410.  
  411. /***********************************************************************
  412.  *                DumpPrefix
  413.  ***********************************************************************
  414.  * SYNOPSIS:        Return state of prefix tables to caller
  415.  * CALLED BY:        PREFIX_DUMP
  416.  * RETURN:        Wheeee.
  417.  * SIDE EFFECTS:    None
  418.  *
  419.  * STRATEGY:
  420.  *    A buffer is filled with the following data:
  421.  *        For each imported prefix:
  422.  *            <type><name>:<options>:<mtd>\n
  423.  *        <type> is one of i (imported, non-temporary), r (root), or
  424.  *        t (temporary). <options> is the string of mount options,
  425.  *        <mtd> is 1 if the prefix is mounted and 0 if it is not.
  426.  *
  427.  *        For each exported prefix:
  428.  *            x<dir>:<name>\n
  429.  *
  430.  * REVISION HISTORY:
  431.  *    Name    Date        Description
  432.  *    ----    ----        -----------
  433.  *    ardeb    7/ 8/89        Initial Revision
  434.  *
  435.  ***********************************************************************/
  436. static void
  437. DumpPrefix(from, msg, len, data, serverData)
  438.     struct sockaddr_in        *from;
  439.     Rpc_Message            msg;
  440.     int                len;
  441.     Rpc_Opaque            data;
  442.     Rpc_Opaque                serverData;    /* Data we gave (UNUSED) */
  443. {
  444.     if (len != 2) {
  445.     Rpc_Error(msg, RPC_BADARGS);
  446.     } else {
  447.     char        *buf;
  448.     LstNode        ln;
  449.     Prefix        *pp;
  450.     char        *cp;
  451.     int         left;
  452.     
  453.     left = len = *(short *)data;
  454.     left -= 1;
  455.  
  456.     /*
  457.      * Allocate a buffer of the proper size.
  458.      */
  459.     cp = buf = (char *)malloc(len+1);
  460.     bzero(buf, len);
  461.  
  462.     for (ln = Lst_First(prefixes); ln != NILLNODE; ln = Lst_Succ(ln)) {
  463.         int        eltlen;
  464.  
  465.         pp = (Prefix *)Lst_Datum(ln);
  466.         eltlen = 1 + strlen(pp->path) + 1 + strlen(pp->options) + 1 + 1 + 1;
  467.  
  468.         if (eltlen < left) {
  469.         sprintf(cp, "%c%s:%s:%c\n",
  470.             ((pp->flags & PREFIX_TEMP) ? 't' :
  471.              ((pp->flags & PREFIX_ROOT) ? 'r' : 'i')),
  472.             pp->path, pp->options,
  473.             (pp->flags & PREFIX_MOUNTED) ? '1' : '0');
  474.         cp += eltlen;
  475.         left -= eltlen;
  476.         }
  477.     }
  478.     
  479.     Export_Dump(cp, &left);
  480.  
  481.     Rpc_Return(msg, len - left + 1, (Rpc_Opaque)buf);
  482.  
  483.     free(buf);
  484.     }
  485. }
  486.  
  487.  
  488. /***********************************************************************
  489.  *                PrintPrefix
  490.  ***********************************************************************
  491.  * SYNOPSIS:        Print the state of the prefix tables
  492.  * CALLED BY:        main
  493.  * RETURN:        Nothing
  494.  * SIDE EFFECTS:    Stuff be printed
  495.  *
  496.  * STRATEGY:
  497.  *
  498.  * REVISION HISTORY:
  499.  *    Name    Date        Description
  500.  *    ----    ----        -----------
  501.  *    ardeb    7/ 8/89        Initial Revision
  502.  *
  503.  ***********************************************************************/
  504. static void
  505. PrintPrefix(server)
  506.     struct sockaddr_in    *server;
  507. {
  508.     char        buf[4096];      /* 4K for now */
  509.     short       len;            /* Place to pass length to Rpc_Call */
  510.     Rpc_Stat    status;
  511.     char        *cp;
  512.     char        *end;
  513.     struct timeval retry;
  514.  
  515.     retry.tv_sec = 1;
  516.     retry.tv_usec = 0;
  517.     
  518.     len = sizeof(buf);
  519.     status = Rpc_Call(prefixSock, server, PREFIX_DUMP,
  520.               sizeof(len), (Rpc_Opaque)&len,
  521.               sizeof(buf), (Rpc_Opaque)buf,
  522.               2, &retry);
  523.  
  524.     if (status != RPC_SUCCESS) {
  525.     fprintf(stderr, "Unable to dump prefix tables: %s\n",
  526.         Rpc_ErrorMessage(status));
  527.     return;
  528.     }
  529.  
  530.     end = buf+sizeof(buf);
  531.     
  532.     printf("IMPORTED PREFIXES:\n");
  533.     printf("Type    Name              Mounted    Options\n");
  534.     printf("============================================\n");
  535.     cp = buf;
  536.  
  537.     while (*cp != 'x' && *cp != '\0' && cp < end) {
  538.     int     namelen,
  539.         optlen;
  540.     char     *cp2;
  541.     char    *type;
  542.     char    *name;
  543.  
  544.     type = ((*cp == 'i') ? "import" : ((*cp == 'r') ? "root" : "temp"));
  545.  
  546.     cp += 1;
  547.     cp2 = (char *)index(cp, ':');
  548.     name = cp;
  549.     namelen = cp2 - name;
  550.  
  551.     cp = cp2+1;
  552.     cp2 = (char *)index(cp, ':');
  553.     optlen = cp2-cp;
  554.     
  555.     printf ("%-8s%-18.*s  %-3s      %.*s\n",
  556.         type,
  557.         namelen, name,
  558.         cp2[1] == '1' ? "yes" : "no",
  559.         optlen, cp);
  560.  
  561.     cp = cp2 + 3;
  562.     }
  563.     printf("\nEXPORTED PREFIXES\n");
  564.     printf("Directory           Exported As           Active?\n");
  565.     printf("=================================================\n");
  566.     
  567.     while (*cp == 'x' && cp < end) {
  568.     int     dirlen;
  569.     char    *cp2;
  570.     char    *dir;
  571.  
  572.     dir = cp+1;
  573.     cp = (char *)index(dir, ':');
  574.     dirlen = cp - dir;
  575.  
  576.     cp += 1;
  577.     cp2 = (char *)index(cp, ':');
  578.     
  579.     printf("%-20.*s%-24.*s%s\n", dirlen, dir, cp2-cp, cp,
  580.            cp2[1] == '1' ? "yes" : "no");
  581.  
  582.     cp = cp2 + 3;
  583.     }
  584. }
  585.     
  586.  
  587. /***********************************************************************
  588.  *                ChangeDebug
  589.  ***********************************************************************
  590.  * SYNOPSIS:        Change the state of debugging
  591.  * CALLED BY:        PREFIX_DEBUG
  592.  * RETURN:        Nothing
  593.  * SIDE EFFECTS:    'debug' is set to the passed value
  594.  *
  595.  * STRATEGY:
  596.  *
  597.  * REVISION HISTORY:
  598.  *    Name    Date        Description
  599.  *    ----    ----        -----------
  600.  *    ardeb    9/13/89        Initial Revision
  601.  *
  602.  ***********************************************************************/
  603. static void
  604. ChangeDebug(from, msg, len, data, serverData)
  605.     struct sockaddr_in        *from;
  606.     Rpc_Message            msg;
  607.     int                len;
  608.     Rpc_Opaque            data;
  609.     Rpc_Opaque                serverData;    /* Data we gave (UNUSED) */
  610. {
  611.     if (len != 4) {
  612.     Rpc_Error(msg, RPC_BADARGS);
  613.     } else {
  614.     if (*(long *)data) {
  615.         debug = *(long *)data;
  616.         dprintf("DEBUGGING ENABLED\n");
  617.     } else {
  618.         dprintf("DEBUGGING DISABLED\n");
  619.         debug = *(long *)data;
  620.     }
  621.     Rpc_Return(msg, 0, (Rpc_Opaque)NULL);
  622.     }
  623. }
  624.  
  625. /***********************************************************************
  626.  *                BeFiendish
  627.  ***********************************************************************
  628.  * SYNOPSIS:        Enter daemon mode
  629.  * CALLED BY:        main
  630.  * RETURN:        Never
  631.  * SIDE EFFECTS:    The process forks...read the code.
  632.  *
  633.  * STRATEGY:
  634.  *
  635.  * REVISION HISTORY:
  636.  *    Name    Date        Description
  637.  *    ----    ----        -----------
  638.  *    ardeb    7/ 8/89        Initial Revision
  639.  *
  640.  ***********************************************************************/
  641. static void
  642. BeFiendish()
  643. {
  644.     int            pid;            /* Child process ID in case we have
  645.                      * a problem in the parent. */
  646.     LstNode         ln;        /* Current prefix node */
  647.     LstNode        next;        /* Node of next prefix to mount */
  648.     
  649.     /*
  650.      * We must be all root to function effectively...
  651.      */
  652.     if (getuid() != 0 || geteuid() != 0) {
  653.     fprintf(stderr, "must be run by root to act as a daemon\n");
  654.     exit(1);
  655.     }
  656.     
  657.     /*
  658.      * Create the socket over which we communicate with everyone but the kernel
  659.      */
  660.     prefixSock = Rpc_UdpCreate(True, PREFIX_PORT);
  661.     if (prefixSock == -1) {
  662.     perror("Rpc_UdpCreate");
  663.     exit(1);
  664.     }
  665.  
  666.     Rpc_ServerCreate(prefixSock, PREFIX_DUMP, DumpPrefix,
  667.              Rpc_SwapShort, NULL, NULL);
  668.     Rpc_ServerCreate(prefixSock, PREFIX_DEBUG, ChangeDebug,
  669.              Rpc_SwapLong, NULL, NULL);
  670.     
  671.     /*
  672.      * Locate exported prefixes and register servers
  673.      */
  674.     Export_Init();
  675.  
  676.     /*
  677.      * Make sure the mount directory's ok
  678.      */
  679.     Mount_Init();
  680.         
  681.     /*
  682.      * Initialize things in the module that manages unmounted prefixes
  683.      */
  684.     Import_Init();
  685.  
  686.     /*
  687.      * Create the "child" process the daemon will use for mounting and
  688.      * unmounting. In reality, they're siblings, but life goes on.
  689.      */
  690.     if (!Child_Init()) {
  691.     exit(1);
  692.     }
  693.     
  694.     /*
  695.      * Mount the existing prefixes on ourself.
  696.      *
  697.      * Register the MOUNT_DIR with the kernel first, only mounting
  698.      * other prefixes if we succeed there.
  699.      */
  700.     if (Mount_MountRoot()) {
  701.     for (ln = Lst_First(prefixes); ln != NILLNODE; ln = next){
  702.         Prefix *pp = (Prefix *)Lst_Datum(ln);
  703.  
  704.         next = Lst_Succ(ln);
  705.  
  706.         if (!Child_Call(pp, PREFIX_MOUNT_LOCAL)) {
  707.         /*
  708.          * Remove the prefix.
  709.          */
  710.         fprintf(stderr, "Couldn't mount %s: deleting\n",
  711.             pp->path);
  712.         free(pp->path);
  713.         next = Lst_Succ(ln);
  714.         (void)Lst_Remove(prefixes, ln);
  715.         }
  716.     }
  717.     } else {
  718.     /*
  719.      * Kill both processes before exiting non-zero
  720.      */
  721.     Message("Couldn't mount %s\n", MOUNT_DIR);
  722.     Child_Kill();
  723.     exit(1);
  724.     }
  725.  
  726.     /*
  727.      * Fork so we can detach from our parent.
  728.      */
  729.     switch (pid = fork()) {
  730.     case 0:
  731.         /*
  732.          * Change our process group so opening the console doesn't make
  733.          * it our controlling terminal. Wouldn't want to be shut out by
  734.          * it or get a HANGUP signal should someone log out on it.
  735.          */
  736.         setpgrp(0, getpid());
  737.         /*
  738.          * Go do our thing after opening stderr to the console for
  739.          * logging purposes.
  740.          */
  741.         freopen("/dev/console", "w", stderr);
  742.         /*
  743.          * Close the other two standard streams so we can be started
  744.          * via an rsh. Otherwise, rshd won't exit...
  745.          */
  746.         close(0);
  747.         close(1);
  748. #ifdef MEM_TRACE
  749.         (void)signal(SIGHUP, DumpMemStats);
  750. #endif /* MEM_TRACE */
  751.         /*
  752.          * Rpc_Run never returns
  753.          */
  754.         dprintf("main prefix daemon alive and running...\n");
  755.         Rpc_Run();
  756.         fprintf(stderr, "Rpc_Run returned!\n");
  757.         exit(1);
  758.     case -1:
  759.         perror("fork");
  760.         Child_Kill();
  761.         exit(1);
  762.         break;
  763.     default:
  764.         exit(0);
  765.     }
  766. }
  767.  
  768. /***********************************************************************
  769.  *                ReadConfigFile
  770.  ***********************************************************************
  771.  * SYNOPSIS:        Read a configuration file
  772.  * CALLED BY:        main
  773.  * RETURN:        1 if successful, 0 if not
  774.  * SIDE EFFECTS:    Things are entered on the prefixes and exports lists
  775.  *
  776.  * STRATEGY:
  777.  *
  778.  * REVISION HISTORY:
  779.  *    Name    Date        Description
  780.  *    ----    ----        -----------
  781.  *    ardeb    7/ 8/89        Initial Revision
  782.  *
  783.  ***********************************************************************/
  784. static int
  785. ReadConfigFile(name)
  786.     char        *name;        /* Name of file to read */
  787. {
  788.     FILE        *cf;        /* Stream open to file */
  789.     char        line[256];  /* Line from file. I can't see it ever getting
  790.                  * this big, but better safe than sorry, no? */
  791.     char        *cp;
  792.     int            num = 1;
  793.     int            retval = 1;
  794.  
  795.     cf = fopen(name, "r");
  796.  
  797.     if (cf == (FILE *)NULL) {
  798.     perror(name);
  799.     return(0);
  800.     }
  801.  
  802.     while (fgets(line, sizeof(line), cf) != NULL) {
  803.     for (cp = line; isspace(*cp); cp++) {
  804.         ;
  805.     }
  806.  
  807.     switch(*cp) {
  808.         case 'i': case 'I':
  809.         case 'r': case 'R':
  810.         {
  811.         /*
  812.          * Import a prefix or prefix root. Usage:
  813.          *
  814.          * import    <prefix>    [<mount options>]
  815.          * root        <prefix>    [<mount options>]
  816.          */
  817.         char    *prefix;
  818.         int     flags = (*cp == 'r' || *cp == 'R') ? PREFIX_ROOT : 0;
  819.         
  820.         /*
  821.          * Skip command
  822.          */
  823.         while (!isspace(*cp) && (*cp != '\0')) {
  824.             cp++;
  825.         }
  826.         /*
  827.          * Skip to prefix
  828.          */
  829.         while (isspace(*cp)) {
  830.             cp++;
  831.         }
  832.         
  833.         if (*cp == '\0') {
  834.            fprintf(stderr,
  835.                "file \"%s\", line %d: %s requires prefix as argument\n",
  836.                name, num, flags ? "root" : "import");
  837.            retval = 0;
  838.         } else {
  839.             Prefix      *pp;    /* New prefix */
  840.             char        save;    /* Character after prefix */
  841.             
  842.             /*
  843.              * Record and skip over prefix
  844.              */
  845.             prefix = cp;
  846.             while (!isspace(*cp) && (*cp != '\0')) {
  847.             cp++;
  848.             }
  849.             /*
  850.              * Save character after prefix so we know if we hit
  851.              * the end of the line.
  852.              */
  853.             save = *cp;
  854.             *cp++ = '\0';
  855.  
  856.             pp = Import_CreatePrefix(prefix);
  857.             if (pp == NULL) {
  858.             retval = 0;
  859.             } else {
  860.             if (save != '\0' && save != '\n') {
  861.                 /*
  862.                  * May be mount options here...
  863.                  */
  864.                 while (isspace(*cp)) {
  865.                 cp++;
  866.                 }
  867.                 if (*cp != '\0') {
  868.                 /*
  869.                  * Rest of the line is options...
  870.                  */
  871.                 int     len;        /* Length of options */
  872.                 
  873.                 /*
  874.                  * Skip to the end of the line, keeping
  875.                  * track of the start of the options.
  876.                  */
  877.                 pp->options = cp;
  878.                 while (*cp != '\n' && *cp != '\0') {
  879.                     cp++;
  880.                 }
  881.  
  882.                 /*
  883.                  * Copy the options into their own buffer
  884.                  */
  885.                 *cp = '\0';
  886.                 len = cp - pp->options;
  887.  
  888.                 cp = (char *)malloc(len+1);
  889.                 strcpy(cp, pp->options);
  890.                 pp->options = cp;
  891.                 }
  892.             }
  893.             /*
  894.              * Set the PREFIX_ROOT flag if appropriate.
  895.              */
  896.             pp->flags |= flags;
  897.             }
  898.         }
  899.         break;
  900.         }
  901.         case 'e': case 'E' : case 'x' : case 'X':
  902.         {
  903.         /*
  904.          * Export a directory as a prefix. Usage:
  905.          *
  906.          * export    <directory>    [<prefix>]
  907.          *
  908.          * If no <prefix> is given, <directory> is used.
  909.          */
  910.         char    *dir;
  911.         char    *prefix;
  912.         
  913.         /*
  914.          * Skip command
  915.          */
  916.         while (!isspace(*cp) && (*cp != '\0')) {
  917.             cp++;
  918.         }
  919.         /*
  920.          * Skip to directory
  921.          */
  922.         while (isspace(*cp)) {
  923.             cp++;
  924.         }
  925.         
  926.         if (*cp == '\0') {
  927.            fprintf(stderr,
  928.                "file \"%s\", line %d: export requires directory, at least\n",
  929.                name, num);
  930.            retval = 0;
  931.         } else {
  932.             /*
  933.              * Record start of, and skip over, directory
  934.              */
  935.             dir = cp;
  936.             while (!isspace(*cp) && (*cp != '\0')) {
  937.             cp++;
  938.             }
  939.  
  940.             if (*cp != '\0') {
  941.             /*
  942.              * Terminate directory and skip to prefix
  943.              */
  944.             *cp++ = '\0';
  945.             while (isspace(*cp)) {
  946.                 cp++;
  947.             }
  948.             if (*cp != '\0') {
  949.                 /*
  950.                  * Actually a prefix here -- use it
  951.                  */
  952.                 prefix = cp;
  953.                 while (!isspace(*cp) && (*cp != '\0')) {
  954.                 cp++;
  955.                 }
  956.                 /*
  957.                  * Terminate the prefix
  958.                  */
  959.                 *cp = '\0';
  960.             } else {
  961.                 /*
  962.                  * Prefix is the same as the directory
  963.                  */
  964.                 prefix = dir;
  965.             }
  966.             } else {
  967.             /*
  968.              * Prefix be the same as the directory.
  969.              */
  970.             prefix = dir;
  971.             }
  972.  
  973.             /*
  974.              * Make permanent copies of the two things
  975.              */
  976.             cp = (char *)malloc(strlen(dir) + 1);
  977.             strcpy(cp, dir);
  978.             dir = cp;
  979.  
  980.             cp = (char *)malloc(strlen(prefix) + 1);
  981.             strcpy(cp, prefix);
  982.             prefix = cp;
  983.  
  984.             /*
  985.              * Record the export of the thing.
  986.              */
  987.             Export_Prefix(dir, prefix);
  988.         }
  989.         break;
  990.         }
  991.         case '\0':
  992.         case '#':
  993.         /*
  994.          * Comment/blank line -- ignore line
  995.          */
  996.         break;
  997.         case 'q': case 'Q':
  998.         /*
  999.          * Be quiet. Usage:
  1000.          *
  1001.          * quiet
  1002.          *
  1003.          */
  1004.         quiet = 1;
  1005.         break;
  1006.         case 'd': case 'D':
  1007.         {
  1008.         /*
  1009.          * Turn on debugging. Usage:
  1010.          *
  1011.          * debug [<logfile> <mode>]
  1012.          *
  1013.          */
  1014.         char    *dbgFile;
  1015.  
  1016.         debug = 1;
  1017.         dbgStream = stderr;
  1018.  
  1019.         while (!isspace(*cp) && *cp != '\0') {
  1020.             cp++;
  1021.         }
  1022.  
  1023.         while (isspace(*cp)) {
  1024.             cp++;
  1025.         }
  1026.  
  1027.         if (*cp != '\0') {
  1028.             dbgFile = cp;
  1029.             while(!isspace(*cp) && *cp != '\0') {
  1030.             cp++;
  1031.             }
  1032.             if (*cp != '\0') {
  1033.             *cp++ = '\0';
  1034.             while(isspace(*cp)) {
  1035.                 cp++;
  1036.             }
  1037.             }
  1038.             if (*cp != 'a' && *cp != 'w') {
  1039.             *cp = 'a';
  1040.             cp[1] = '\0';
  1041.             }
  1042.             dbgStream = fopen(dbgFile, cp);
  1043.             if (dbgStream == NULL) {
  1044.             fprintf(stderr, "can't open debug log \"%s\"\n",
  1045.                 dbgFile);
  1046.             dbgStream = stderr;
  1047.             } else {
  1048.             time_t    now;
  1049.  
  1050.             time(&now);
  1051.             fprintf(dbgStream, "prefix: Start %s", ctime(&now));
  1052.             }
  1053.         }
  1054.         break;
  1055.         }
  1056.         default:
  1057.         fprintf(stderr, "\"%s\" command unknown\n",
  1058.             cp);
  1059.         retval = 0;
  1060.         break;
  1061.     }
  1062.     num++;
  1063.     }
  1064.     fclose(cf);
  1065.     return(retval);
  1066. }
  1067.     
  1068.  
  1069. /***********************************************************************
  1070.  *                main
  1071.  ***********************************************************************
  1072.  * SYNOPSIS:        Initialization
  1073.  * CALLED BY:        UNIX
  1074.  * RETURN:        Nothing
  1075.  * SIDE EFFECTS:    Process forks and parent goes away.
  1076.  *
  1077.  * STRATEGY:
  1078.  *
  1079.  * REVISION HISTORY:
  1080.  *    Name    Date        Description
  1081.  *    ----    ----        -----------
  1082.  *    ardeb    7/ 5/89        Initial Revision
  1083.  *
  1084.  ***********************************************************************/
  1085. main(argc, argv)
  1086.     int            argc;
  1087.     char        **argv;
  1088. {
  1089.     Prefix    *pp;        /* Prefix being added */
  1090.     int        i;          /* Index into argv */
  1091.     int           daemon=0;   /* Non-zero if should enter daemon mode */
  1092.     Lst        delete;        /* List of prefixes to be deleted */
  1093.     Lst            noex;        /* List of prefixes to stop exporting */
  1094.     int            printem=0;  /* Non-zero if should request all prefixes and
  1095.                  * print them. */
  1096.     int            debugon=0;  /* Non-zero if should turn debugging on */
  1097.     int            debugoff=0; /* Non-zero if should turn debugging off */
  1098.  
  1099.     /*
  1100.      * Initialize the lists on which Prefixes can reside
  1101.      */
  1102.     prefixes = Lst_Init(FALSE);
  1103.     freePrefixes = Lst_Init(FALSE);
  1104.     delete = Lst_Init(FALSE);
  1105.     noex = Lst_Init(FALSE);
  1106.  
  1107.     dbgStream = stderr;
  1108.  
  1109.     for (i = 1; i < argc; i++) {
  1110.     if (argv[i][0] == '-') {
  1111.         switch(argv[i][1]) {
  1112.         case 'D':
  1113.             daemon = 1;
  1114.             if (argv[i][2] == 'D') {
  1115.             debug = 1;
  1116.             }
  1117.             break;
  1118.         case 'd':
  1119.             if (strcmp(argv[i], "-debug") == 0) {
  1120.             debugon=1; debugoff=0;
  1121.             } else {
  1122.             /*
  1123.              * Delete a prefix (not valid in daemon mode)
  1124.              */
  1125.             if (i+1 == argc) {
  1126.                 fprintf(stderr,
  1127.                     "-d requires prefix as argument\n");
  1128.                 goto usage;
  1129.             } else {
  1130.                 (void)Lst_AtEnd(delete, (ClientData)argv[i+1]);
  1131.             }
  1132.             i += 1;
  1133.             }
  1134.             break;
  1135.         case 'f':
  1136.             /*
  1137.              * Read configuration from a file. This implies we're
  1138.              * in daemon mode.
  1139.              */
  1140.             if (i+1 == argc) {
  1141.             fprintf(stderr, "-f requires filename as argument\n");
  1142.             goto usage;
  1143.             } else if (ReadConfigFile(argv[i+1])) {
  1144.             daemon = 1;
  1145.             }
  1146.             i += 1;
  1147.             break;
  1148.         case 'i':
  1149.             /*
  1150.              * Import a prefix
  1151.              */
  1152.             if (i+1 == argc) {
  1153.             fprintf(stderr, "-i requires prefix as argument\n");
  1154.             goto usage;
  1155.             } else {
  1156.             dprintf("-i %s\n", argv[i+1]);
  1157.             (void)Import_CreatePrefix(argv[i+1]);
  1158.             }
  1159.             i += 1;
  1160.             break;
  1161.         case 'n':
  1162.             if (strcmp(argv[i], "-nodebug") == 0) {
  1163.             debugoff = 1; debugon = 0;
  1164.             } else {
  1165.             goto usage;
  1166.             }
  1167.             break;
  1168.         case 'p':
  1169.             /*
  1170.              * Print all known prefixes after processing everything
  1171.              * else.
  1172.              */
  1173.             printem = 1;
  1174.             break;
  1175.         case 'q':
  1176.             quiet = 1;
  1177.             break;
  1178.         case 'r':
  1179.             /*
  1180.              * Import prefixes under a root
  1181.              */
  1182.             if (i+1 == argc) {
  1183.             fprintf(stderr, "-r requires prefix as argument\n");
  1184.             goto usage;
  1185.             } else {
  1186.             dprintf("-r %s\n", argv[i+1]);
  1187.             pp = Import_CreatePrefix(argv[i+1]);
  1188.  
  1189.             if (pp != NULL) {
  1190.                 pp->flags = PREFIX_ROOT;
  1191.             }
  1192.             }
  1193.             i += 1;
  1194.             break;
  1195.         case 'x':
  1196.             /*
  1197.              * Export a directory under a prefix
  1198.              */
  1199.             if (i+1 == argc) {
  1200.             fprintf(stderr,
  1201.                 "-x requires at least a directory\n");
  1202.             goto usage;
  1203.             } else {
  1204.             if ((i + 2 < argc) && argv[i+2][0] != '-') {
  1205.                 dprintf("-x %s %s\n", argv[i+1], argv[i+2]);
  1206.                 Export_Prefix(argv[i+1], argv[i+2]);
  1207.                 i += 2;
  1208.             } else {
  1209.                 dprintf("-x %s %s\n", argv[i+1], argv[i+1]);
  1210.                 Export_Prefix(argv[i+1], argv[i+1]);
  1211.                 i += 1;
  1212.             }
  1213.             }
  1214.             break;
  1215.         case 'X':
  1216.             /*
  1217.              * Stop exporting a prefix.
  1218.              */
  1219.             if (i+1 == argc) {
  1220.             fprintf(stderr,
  1221.                 "-X requires a prefix to stop exporting");
  1222.             goto usage;
  1223.             } else {
  1224.             (void)Lst_AtEnd(noex, argv[i+1]);
  1225.             i += 1;
  1226.             }
  1227.             break;
  1228.         default:
  1229.             fprintf(stderr, "-%c unknown\n", argv[i][1]);
  1230.         usage:
  1231.             fprintf(stderr,
  1232.                 "%s [-D[D]] [[-f] <file>] [-i <prefix>] [-x <fs> [<prefix>]] [-r <prefix>]\n",
  1233.                 argv[0]);
  1234.             fprintf(stderr, "\t[-d <prefix>] [-debug] [-nodebug] [-X <prefix>]\n");
  1235.             exit(1);
  1236.         }
  1237.     } else if (ReadConfigFile(argv[i])) {
  1238.         daemon = 1;
  1239.     }
  1240.     }
  1241.     
  1242. #ifdef MEM_TRACE
  1243.     /*
  1244.      * Set heap debugging based on debug flag
  1245.      */
  1246.     if (debug) {
  1247.     malloc_debug(2);
  1248.     } else {
  1249.     malloc_debug(1);
  1250.     }
  1251. #endif
  1252.  
  1253.     if (daemon) {
  1254.     if (!Lst_IsEmpty(delete)) {
  1255.         fprintf(stderr, "Warning: -d ignored in daemon mode\n");
  1256.     }
  1257.     if (printem) {
  1258.         fprintf(stderr, "Warning: -p ignored in daemon mode\n");
  1259.     }
  1260.     
  1261.     BeFiendish();
  1262.     } else {
  1263.     /*
  1264.      * Tell daemon about new things to export/import and things to
  1265.      * blow away.
  1266.      */
  1267.     LstNode            ln;    /* For traversing prefixes list */
  1268.     struct timeval    retry;    /* Retry interval for Rpc_Call */
  1269.     Rpc_Stat    status;    /* Status of call */
  1270.     struct sockaddr_in sin;    /* Address of local server */
  1271.  
  1272.     /*
  1273.      * Set up address to contact daemon on local machine.
  1274.      */
  1275.     sin.sin_family = AF_INET;
  1276.     sin.sin_port = htons(PREFIX_PORT);
  1277.     sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  1278.     
  1279.     /*
  1280.      * Retransmit every second...
  1281.      */
  1282.     retry.tv_sec = 1;
  1283.     retry.tv_usec = 0;
  1284.     
  1285.     /*
  1286.      * Create calling socket
  1287.      */
  1288.     prefixSock = Rpc_UdpCreate(FALSE, 0);
  1289.     if (prefixSock < 0) {
  1290.         perror("Rpc_UdpCreate");
  1291.         exit(1);
  1292.     }
  1293.  
  1294.     /*
  1295.      * All the prefixes we recorded need to be forward to the proper
  1296.      * procedure in the local daemon.
  1297.      */
  1298.     for (ln = Lst_First(prefixes); ln != NILLNODE; ln = Lst_Succ(ln)) {
  1299.         pp = (Prefix *)Lst_Datum(ln);
  1300.         
  1301.         status = Rpc_Call(prefixSock, &sin,
  1302.                  (pp->flags & PREFIX_ROOT) ?
  1303.                  PREFIX_IMPORT_ROOT : PREFIX_IMPORT,
  1304.                  strlen(pp->path) + 1, (Rpc_Opaque)pp->path,
  1305.                  0, (Rpc_Opaque)NULL,
  1306.                  2, &retry);
  1307.  
  1308.         if (status != RPC_SUCCESS) {
  1309.         if (status == DUPLICATE_PREFIX) {
  1310.             fprintf(stderr, "already importing %s\n", pp->path);
  1311.         } else {
  1312.             fprintf(stderr, "couldn't import %s: %s\n", pp->path,
  1313.                 Rpc_ErrorMessage(status));
  1314.         }
  1315.         }
  1316.     }
  1317.  
  1318.     /*
  1319.      * Let the export module tell the local daemon what to export, since
  1320.      * all its data are hidden.
  1321.      */
  1322.     Export_Send(&sin);
  1323.  
  1324.     /*
  1325.      * Tell the local daemon to delete any prefixes we were asked to
  1326.      * delete.
  1327.      */
  1328.     for (ln = Lst_First(delete); ln != NILLNODE; ln = Lst_Succ(ln)) {
  1329.         char    *prefix = (char *)Lst_Datum(ln);
  1330.         char    response[128];
  1331.  
  1332.         status = Rpc_Call(prefixSock, &sin,
  1333.                   PREFIX_DELETE,
  1334.                   strlen(prefix) + 1, (Rpc_Opaque)prefix,
  1335.                   sizeof(response), (Rpc_Opaque)response,
  1336.                   2, &retry);
  1337.         if (status != RPC_SUCCESS) {
  1338.         fprintf(stderr, "couldn't delete %s: %s\n", prefix,
  1339.             Rpc_ErrorMessage(status));
  1340.         } else if (strcmp(response, "Ok") != 0) {
  1341.         fprintf(stderr, "couldn't delete %s: %s\n", prefix,
  1342.             response);
  1343.         }
  1344.     }
  1345.  
  1346.     /*
  1347.      * Tell the local daemon to stop exporting any prefixes we were asked
  1348.      * to hide.
  1349.      */
  1350.     for (ln = Lst_First(noex); ln != NILLNODE; ln = Lst_Succ(ln)) {
  1351.         char        *prefix = (char *)Lst_Datum(ln);
  1352.         char        response[1024];
  1353.  
  1354.         status = Rpc_Call(prefixSock, &sin,
  1355.                   PREFIX_NOEXPORT,
  1356.                   strlen(prefix) + 1, (Rpc_Opaque)prefix,
  1357.                   sizeof(response), (Rpc_Opaque)response,
  1358.                   2, &retry);
  1359.         if (status != RPC_SUCCESS) {
  1360.         fprintf(stderr, "Couldn't revoke %s: %s\n", prefix,
  1361.             Rpc_ErrorMessage(status));
  1362.         } else if (strcmp(response, "Ok") != 0) {
  1363.         fprintf(stderr, "Couldn't revoke %s: %s\n",
  1364.             prefix, response);
  1365.         }
  1366.     }
  1367.  
  1368.     /*
  1369.      * If want to see all the prefixes, do that now.
  1370.      */
  1371.     if (printem) {
  1372.         PrintPrefix(&sin);
  1373.     }
  1374.  
  1375.     /*
  1376.      * Change the debugging state now if requested.
  1377.      */
  1378.     if (debugon || debugoff) {
  1379.         long    state = debugon;
  1380.  
  1381.         status = Rpc_Call(prefixSock, &sin,
  1382.                   PREFIX_DEBUG,
  1383.                   sizeof(state), (Rpc_Opaque)&state,
  1384.                   0, (Rpc_Opaque)NULL,
  1385.                   2, &retry);
  1386.         if (status != RPC_SUCCESS) {
  1387.         fprintf(stderr, "couldn't turn %s debugging: %s\n",
  1388.             debugon ? "on" : "off",
  1389.             Rpc_ErrorMessage(status));
  1390.         }
  1391.     }
  1392.     
  1393.     exit(0);
  1394.     }
  1395. }
  1396.